package dashboard.controller;

import java.sql.Timestamp;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;

import net.sf.json.JSONObject;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import dashboard.model.Constant;
import dashboard.model.OnDemandReport;
import dashboard.model.ParamMaster;
import dashboard.model.RealTimeStatResult;
import dashboard.model.SnapshotStatResult;
import dashboard.service.RealTimeDbStatService;
import dashboard.service.SnapshotReportService;
import dashboard.utils.DashboardDateUtils;
import dashboard.utils.ReportUtil;

/**
 * this controller is response all request for report use!
 * @author junwei_ma
 *
 */
@Controller
public class ReportController {

	private static final Log log = LogFactory.getLog(ReportController.class);
	
	private static final String FIRSTLEVEL = "level1page";
	private static final String SECONDLEVEL = "level2page";
	private static final String THIRDLEVEL = "level3page";
	private static final String ONDEMAND = "ondemand";
	
	@Autowired
	private RealTimeDbStatService realTimeService;
	
	@Autowired
	private SnapshotReportService snapshotService;
	
	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView doGet(){
		double xUnit = realTimeService.getParamMaster().getxVal();
		return new ModelAndView(FIRSTLEVEL, "x", xUnit);
	}
	
	@RequestMapping(value="/ondemand", method = RequestMethod.GET)
	public String onDemand(){
		return ONDEMAND;
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public @ResponseBody String firstLevelDetail(@RequestParam("type") String type)
		throws Exception{
		JSONObject json = new JSONObject();
		ParamMaster pm = realTimeService.getParamMaster();
		RealTimeStatResult result = null;
		double bar1 = 0, bar2 = 0;
		
		String label = "";
		if(type.equals(Constant.SHARED_POOL)){
			result = realTimeService.getSharedPoolStat();
			bar1 = pm.getSmAttn();
			bar2 = pm.getSmHealthy();
			label = "Execute to Parse";
		}else if(type.equals(Constant.BUFFER_CACHE)){
			result = realTimeService.getBufferCacheStat();	
			bar1 = pm.getBcAttn();
			bar2 = pm.getBcHealthy();
			label = "Buffer Cache Hit Ratio";
		}else if(type.equals(Constant.REDO_LOG)){
			result = realTimeService.getRedoLogBufferStat();
			bar1 = pm.getRdAttn();
			bar2 = pm.getRdHealthy();
			label = "Redo NoWait";
		}else if(type.equals(Constant.SORTING_MEM)){
			result = realTimeService.getSortMemStat();
			bar1 = pm.getSmAttn();
			bar2 = pm.getSmHealthy();
			label = "In-memory Sort";
		}else{
			throw new Exception("not implemented for " + type + " statistic");
		}		
		
		json.put("title", label);
		json.put("bar1", bar1);
		json.put("bar2", bar2);
		json.put("indicator", result.getIndicator());
		json.put("content", result.getContent());
		json.put("suggestion", result.getSuggestion());
		
		return json.toString();	
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView secondLevelDetail(
			@RequestParam("startTime")String startTimeStr, 
			@RequestParam("endTime")String endTimeStr, 
			@RequestParam("xUnit")double xUnit) throws ParseException{

		Map<String, Object> paramMap = new HashMap<String, Object>();
		
		Timestamp startTime = DashboardDateUtils.constructTimestamp(startTimeStr);
		Timestamp endTime = DashboardDateUtils.constructTimestamp(endTimeStr);
//		snapshotService.test();
		SnapshotStatResult result = snapshotService.getRatio(startTime, endTime, (long)xUnit * 3600);
		
		paramMap.put("result", result);
		paramMap.put("y", snapshotService.getParamMaster().getyVal());
		// this is for debug use
//		for(Point point : result.results.get(0).points){
//			Timestamp timestamp = new Timestamp(point.getX());
//			System.out.println(point.getX() + "========>" + timestamp);
//		}
		
		return new ModelAndView(SECONDLEVEL, paramMap);
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView thirdLevelDetail(@RequestParam("yUnit")double yUnit, 
			@RequestParam("xInterval")String xInterval) throws Exception{
		
		Map<String, Object> paramMap = new HashMap<String, Object>();
		
		String[] interval = xInterval.split("to");
		if(interval.length != 2){
			log.debug("x unit interval select options error");
			return null;
		}
		// get xInterval and populate startTime, endTime for each units w.r.t yUnit.
		Timestamp startTime = Timestamp.valueOf(interval[0]);
		Timestamp endTime = Timestamp.valueOf(interval[1]);
		
		SnapshotStatResult result = snapshotService.getRatio(startTime, endTime, (long)yUnit * 60);
		
		paramMap.put("result", result);
		// get the result and draw the chart.
		// return to thirdlevel page.
		return new ModelAndView(THIRDLEVEL, paramMap);
	}
	
//	@RequestMapping(method = RequestMethod.GET, value="chart")
//	public void drawChart(HttpServletRequest request, HttpServletResponse response)
//            throws ServletException, IOException {
//		
//		response.setContentType("image/png");
//		JFreeChart chart = ReportUtil.createFirstLevelChart(ReportUtil.createDataset2(), "Demo");
//		try{
//			ChartUtilities.writeChartAsPNG(response.getOutputStream(), chart, 500, 500);
//			response.getOutputStream().close();
//		}catch(Exception e){
//			e.printStackTrace();
//		}
//	}
	@RequestMapping(value="/ondemand", method = RequestMethod.POST)
	public @ResponseBody String onDemand(@RequestParam("start")String start, @RequestParam("end")String end){
		JSONObject json = new JSONObject();	
		try{
			Timestamp startTime = DashboardDateUtils.constructTimestamp(start);
			Timestamp endTime = DashboardDateUtils.constructTimestamp(end);
			OnDemandReport report = snapshotService.getOnDemandReport(startTime, endTime);
			json.put("reports", report.getHtmlReports());
		}catch(Exception e){
			json.put("reports", e.toString());
		}
		
		
		return json.toString();
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public @ResponseBody byte[] statistic(@RequestParam("type")String type, @RequestParam("date")String date, 
			@RequestParam("xStart")String xStart, @RequestParam("xEnd")String xEnd) throws Exception{
		
		JFreeChart chart = ReportUtil.createFirstLevelChart(66.5, 500, 500, Constant.BUFFER_CACHE, 
				"Cost", 0, 50, 70, 100);

		byte[] imageBuffer = Base64.encodeBase64(ChartUtilities.encodeAsPNG(chart.createBufferedImage(500, 500)));
		return imageBuffer;
	}
	
	
//	@RequestMapping(method = RequestMethod.GET, value="html")
//	public ModelAndView generateHtmlReport(HttpServletRequest request, HttpServletResponse response)
//            throws ServletException, IOException {
//
////        logger.info("Generate HTML Report!");
////        
////        List<Report> reportsList = new ArrayList<Report>();
////        double period = 2.4;
////        for(double i= 0; i<= 24; i+=10){
////        	Report report = new Report();
////        	report.startTime = i ;
////        	report.endTime = i + period;
////        	     	
////        	report.sharedPool = i;
////        	report.redoLog = i - 1;
////        	report.sorting = i - 2;
////        	report.bufferCache = i - 3;
////        	
////        	report.unit = "h";
////        	
////        	reportsList.add(report);
////        }
////        
////        JRDataSource jrDataSource = new JRBeanCollectionDataSource(reportsList);
////        
////        return new ModelAndView("htmlReport", "datasource", jrDataSource);
//		response.setContentType("image/png");
//		
//		
////		JFreeChart chart = Utils.createChart(Utils.createDataset(), "Demo Chart");
//		JFreeChart chart = ReportUtil.createFirstLevelChart(ReportUtil.createDataset2(), "Demo");
//		
//		
//		try{
//			ChartUtilities.writeChartAsPNG(response.getOutputStream(), chart, 400, 400);
//			response.getOutputStream().close();
//		}catch(Exception e){
//			e.printStackTrace();
//		}
//		return new ModelAndView();
//	}
	
//	 @RequestMapping(method = RequestMethod.GET, value="pdf")
//	 public ModelAndView generatePdfReport(ModelAndView modelAndView){
//	 
//	        log.debug("--------------generate PDF report----------");
//	        Map<String, Object> paramMap = new HashMap<String, Object>();
//	        
//	        List<Report> reportsList = new ArrayList<Report>();
//	        double period = 6;
//	        for(double i= 0; i< 24; i+=period){
//	        	Report report = new Report();
//	        	report.startTime = i;
//	        	report.endTime = i + period;
//	        	     	
//	        	report.sharedPool = i;
//	        	report.redoLog = i - 1;
//	        	report.sorting = i - 2;
//	        	report.bufferCache = i - 3;
//	        	report.unit = "h";
//	        	
//	        	reportsList.add(report);
//	        }
//	        
//	        JRDataSource jrDataSource = new JRBeanCollectionDataSource(reportsList);
//	        paramMap.put("datasource", jrDataSource);
//	        //pdfReport bean has ben declared in the jasper-views.xml file
//	        modelAndView = new ModelAndView("pdfReport", paramMap);
//	 
//	        return modelAndView;
//	 
//	    }//generatePdfReport
	
//	@RequestMapping(method = RequestMethod.POST)
//	public @ResponseBody String stat(@RequestParam("type")String type) throws Exception{
//		
//		JSONObject json = new JSONObject();	
//		RealTimeStatResult result = null;
//		JFreeChart chart = null;
//		
//		ParamMaster pm = realTimeService.getParamMaster();
//		
//		if(type.equals(Constant.SHARED_POOL)){
////			returnValue = realTimeService.getSharedPoolStat();
//			result = realTimeService.getSharedPoolStat();
//			
//			chart = ReportUtil.createFirstLevelChart(result.getIndicator(), 500, 500, Constant.SHARED_POOL, 
//					"Cost", 0, pm.getSpAttn(), pm.getSpHealthy(), 100);
//			
//		}else if(type.equals(Constant.BUFFER_CACHE)){
//			result = realTimeService.getBufferCacheStat();
//					
//			chart = ReportUtil.createFirstLevelChart(result.getIndicator(), 500, 500, Constant.BUFFER_CACHE, 
//					"Cost", 0, pm.getBcAttn(), pm.getBcHealthy(), 100);
////			JFreeChart chart = ReportUtil.createFirstLevelChart(66.5, 500, 500, Constant.BUFFER_CACHE, 
////					"Cost", 0, 50, 70, 100);		
//			
//		}else if(type.equals(Constant.REDO_LOG)){
//			result = realTimeService.getRedoLogBufferStat();
//			
//			chart = ReportUtil.createFirstLevelChart(result.getIndicator(), 500, 500, Constant.REDO_LOG, 
//					"Cost", 0, pm.getRdAttn(), pm.getRdHealthy(), 100);
//		}else if(type.equals(Constant.SORTING_MEM)){
////			returnValue = realTimeService.getSortMemStat();
//			result = realTimeService.getSortMemStat();
//			
//			chart = ReportUtil.createFirstLevelChart(result.getIndicator(), 500, 500, Constant.SORTING_MEM, 
//					"Cost", 0, pm.getSmAttn(), pm.getSmHealthy(), 100);
//		}else{
//			throw new Exception("not implemented for " + type + " statistic");
//		}		
//		
//		json.put("image", new String(Base64.encodeBase64(ChartUtilities.encodeAsPNG(chart.createBufferedImage(500, 500))), "utf-8"));			
//		json.put("content", result.getContent());
//		return json.toString();	
//	}
}
